package com.kylin.core.marketing.query.handler;

import com.kylin.dal.entity.marketing.MarketingBoardEntry;
import com.kylin.dal.entity.marketing.MarketingCampaignEntry;
import com.kylin.dal.entity.marketing.QMarketingBoardEntry;
import com.kylin.dal.entity.marketing.QMarketingCampaignEntry;
import com.kylin.domain.marketing.command.FindCampaignByCommodityCommand;
import com.kylin.domain.marketing.command.FindMarketingCommodityCommand;
import com.kylin.domain.marketing.command.QueryMarketingCampaignCommand;
import com.kylin.domain.marketing.vo.MarketingCampaignVO;
import com.kylin.domain.marketing.vo.MarketingCommodityVO;
import com.kylin.shared.common.PageResults;
import com.kylin.shared.common.consts.Constants;
import com.kylin.shared.enums.CampaignState;
import com.kylin.shared.enums.MarketingType;
import com.kylin.shared.enums.RunningState;
import com.kylin.shared.enums.YesNoEnum;
import com.kylin.shared.utils.MappingTools;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import org.axonframework.queryhandling.QueryHandler;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.persistence.EntityManager;
import java.util.List;
import java.util.Objects;

/**
 * 营销数据查询
 * @author Damon S.
 * @version v1.0.1
 * @date 2020年12月20日 13:30
 */
@Slf4j
@Component
public class MarketingQueryHandler {

    private final QMarketingCampaignEntry qMarketingCampaignEntry;
    private final QMarketingBoardEntry qMarketingBoardEntry;
    private final JPAQueryFactory marketingQueryFactory;

    private final MarketingTranslator marketingTranslator;

    public MarketingQueryHandler(@Qualifier("kylinArtworkEntityManager")
                                         EntityManager entityManager,
                                 MarketingTranslator marketingTranslator) {
        this.marketingQueryFactory = new JPAQueryFactory(entityManager);
        this.qMarketingCampaignEntry = QMarketingCampaignEntry.marketingCampaignEntry;
        this.qMarketingBoardEntry = QMarketingBoardEntry.marketingBoardEntry;

        this.marketingTranslator = marketingTranslator;
    }

    @QueryHandler
    private PageResults queryMarketingCampaigns(QueryMarketingCampaignCommand command) {
        long currentEpochSecond = MappingTools.toCurrentEpochSecond();
        // 构建查询条件
        BooleanExpression expression = qMarketingCampaignEntry.type.eq(command.getType().getCode())
                .and(qMarketingBoardEntry.state.eq(RunningState.RUNNING.getCode()))
                .and(qMarketingCampaignEntry.stopAt.goe(currentEpochSecond))
                .and(qMarketingCampaignEntry.startAt.loe(currentEpochSecond))
                .and(qMarketingCampaignEntry.campaignState.eq(CampaignState.PUBLISHED.getCode()))
                .and(qMarketingBoardEntry.removed.eq(YesNoEnum.N.getCode()));
        // 构建查询语句儿
        QueryResults<MarketingBoardEntry> results = this.marketingQueryFactory
                .selectFrom(qMarketingBoardEntry)
                .leftJoin(qMarketingCampaignEntry)
                .on(qMarketingBoardEntry.campaignId.eq(qMarketingCampaignEntry.campaignId))
                .where(expression)
                .limit(command.getPageSize())
                .offset((command.getPageIndex() - Constants.LONG_ONE) * command.getPageSize())
                .fetchResults();
        // 返回查询结果
        return PageResults.builder()
                .limit(results.getLimit())
                .total(results.getTotal())
                .index(results.getOffset() / results.getLimit() + Constants.LONG_ONE)
                .results(marketingTranslator.toMarketingBoardRespDTO(results.getResults()))
                .build();
    }

    @QueryHandler
    private MarketingCampaignVO findCampaignByCommodityId(FindCampaignByCommodityCommand command) {
        long currentEpochSecond = MappingTools.toCurrentEpochSecond();
        // 构建查询条件
        BooleanExpression expression = qMarketingCampaignEntry.type.ne(MarketingType.NA.getCode())
                .and(qMarketingBoardEntry.commodityId.eq(command.getCommodityId()))
                .and(qMarketingBoardEntry.state.eq(RunningState.RUNNING.getCode()))
                .and(qMarketingCampaignEntry.startAt.loe(currentEpochSecond))
                .and(qMarketingCampaignEntry.stopAt.goe(currentEpochSecond))
                .and(qMarketingCampaignEntry.campaignState.eq(CampaignState.PUBLISHED.getCode()))
                .and(qMarketingBoardEntry.removed.eq(YesNoEnum.N.getCode()));
        // 构建查询语句儿
        List<MarketingCampaignEntry> campaigns = marketingQueryFactory
                .selectFrom(qMarketingCampaignEntry)
                .leftJoin(qMarketingBoardEntry)
                .on(qMarketingCampaignEntry.campaignId.eq(qMarketingBoardEntry.campaignId))
                .where(expression)
                .fetch();
        if (CollectionUtils.isEmpty(campaigns) || campaigns.size() > Constants.INT_ONE) {
            return MarketingCampaignVO.EMPTY;
        }
        // 对象转换，返回查询结果
        return marketingTranslator.toCampaignVO(campaigns.get(0));
    }

    @QueryHandler
    public MarketingCommodityVO findMarketingCommodity(FindMarketingCommodityCommand command) {
        MarketingBoardEntry boardCommodityEntry = marketingQueryFactory.selectFrom(qMarketingBoardEntry)
                .where(qMarketingBoardEntry.commodityId.eq(command.getCommodityId())
                        .and(qMarketingBoardEntry.boardId.eq(command.getBoardId())))
                .fetchOne();
        return Objects.isNull(boardCommodityEntry) ?
                MarketingCommodityVO.EMPTY :
                marketingTranslator.toMarketingCommodityVO(boardCommodityEntry);
    }
}
